"""
从高德地图API同步景点数据（包括图片）
"""
import time
from django.core.management.base import BaseCommand
from django.conf import settings
from apps.attractions.models import Attraction, AttractionImage
from utils.amap_client import AMapClient
from utils.image_utils import create_image_file_from_url
from decimal import Decimal


class Command(BaseCommand):
    help = '从高德地图API同步南昌景点数据（包括图片）'

    def add_arguments(self, parser):
        parser.add_argument(
            '--keywords',
            type=str,
            default='',
            help='搜索关键词，多个关键词用逗号分隔'
        )
        parser.add_argument(
            '--location',
            type=str,
            default='115.89,28.68',
            help='中心点坐标，格式：经度,纬度（默认：南昌市中心）'
        )
        parser.add_argument(
            '--radius',
            type=int,
            default=50000,
            help='搜索半径（米），默认50000（50公里）'
        )
        parser.add_argument(
            '--max-count',
            type=int,
            default=100,
            help='最大同步数量，默认100'
        )
        parser.add_argument(
            '--skip-images',
            action='store_true',
            help='跳过图片下载（仅同步景点基本信息）'
        )
        parser.add_argument(
            '--update-existing',
            action='store_true',
            help='更新已存在的景点数据'
        )

    def handle(self, *args, **options):
        # 检查API Key
        api_key = settings.AMAP_CONFIG.get('API_KEY')
        if not api_key or api_key == 'your_amap_api_key':
            self.stdout.write(
                self.style.ERROR('❌ 高德地图API Key未配置！')
            )
            self.stdout.write(
                self.style.WARNING('请在 settings.py 中设置 AMAP_CONFIG[\'API_KEY\']')
            )
            return

        # 初始化高德地图客户端
        amap_client = AMapClient(api_key)

        keywords = options['keywords']
        location = options['location']
        radius = options['radius']
        max_count = options['max_count']
        skip_images = options['skip_images']
        update_existing = options['update_existing']

        self.stdout.write(self.style.SUCCESS('=' * 60))
        self.stdout.write(self.style.SUCCESS('开始从高德地图API同步景点数据'))
        self.stdout.write(self.style.SUCCESS('=' * 60))
        self.stdout.write(f'搜索位置: {location}')
        self.stdout.write(f'搜索半径: {radius}米')
        self.stdout.write(f'关键词: {keywords if keywords else "无"}')
        self.stdout.write(f'最大数量: {max_count}')
        self.stdout.write(f'跳过图片: {"是" if skip_images else "否"}')
        self.stdout.write(f'更新已存在: {"是" if update_existing else "否"}')
        self.stdout.write('')

        # 搜索景点
        try:
            if keywords:
                # 使用关键词搜索
                keywords_list = [k.strip() for k in keywords.split(',')]
                all_pois = []
                for keyword in keywords_list:
                    self.stdout.write(f'搜索关键词: {keyword}')
                    page = 1
                    while len(all_pois) < max_count:
                        result = amap_client.search_pois_by_keyword(
                            keyword=keyword,
                            city='南昌市',
                            page=page,
                            page_size=20
                        )
                        pois = result.get('pois', [])
                        if not pois:
                            break
                        all_pois.extend(pois)
                        if len(pois) < 20:
                            break
                        page += 1
                        time.sleep(0.2)  # 避免请求过快
            else:
                # 使用位置搜索
                all_pois = []
                page = 1
                while len(all_pois) < max_count:
                    result = amap_client.search_pois_by_location(
                        location=location,
                        radius=radius,
                        page=page,
                        page_size=20
                    )
                    pois = result.get('pois', [])
                    if not pois:
                        break
                    all_pois.extend(pois)
                    if len(pois) < 20:
                        break
                    page += 1
                    time.sleep(0.2)  # 避免请求过快

            # 限制数量
            all_pois = all_pois[:max_count]

            self.stdout.write(f'\n找到 {len(all_pois)} 个POI，开始同步...\n')

            created_count = 0
            updated_count = 0
            image_count = 0
            error_count = 0

            for idx, poi in enumerate(all_pois, 1):
                try:
                    # 从搜索结果中获取POI ID（这是主要的POI ID）
                    poi_id_from_search = poi.get('id', '')
                    poi_name = poi.get('name', '')
                    poi_location = poi.get('location', '').split(',')
                    
                    if not poi_location or len(poi_location) < 2:
                        self.stdout.write(
                            self.style.WARNING(f'[{idx}/{len(all_pois)}] 跳过 {poi_name}: 坐标无效')
                        )
                        continue

                    longitude = Decimal(poi_location[0])
                    latitude = Decimal(poi_location[1])
                    address = poi.get('address', '')
                    tel = poi.get('tel', '')
                    type_code = poi.get('type', '')
                    
                    # 获取POI详情（包含图片和更多信息）
                    poi_detail = None
                    poi_data = None
                    try:
                        time.sleep(0.2)  # 避免请求过快
                        poi_detail = amap_client.get_poi_detail(poi_id_from_search)
                        
                        # 调试：打印POI详情结构
                        self.stdout.write(f'  POI详情响应状态: {poi_detail.get("status") if poi_detail else "无响应"}')
                        
                        if poi_detail and poi_detail.get('status') == '1':
                            if poi_detail.get('pois'):
                                poi_data = poi_detail.get('pois')[0]
                                # 调试：打印POI数据字段
                                self.stdout.write(f'  POI数据字段: {list(poi_data.keys())[:15]}')
                                
                                # 检查图片数据
                                photos = poi_data.get('photos', [])
                                if photos:
                                    self.stdout.write(f'  找到 {len(photos)} 张图片')
                                    if isinstance(photos, list) and len(photos) > 0:
                                        self.stdout.write(f'  第一张图片数据: {photos[0]}')
                                else:
                                    self.stdout.write(f'  未找到photos字段，尝试其他字段...')
                                    # 尝试其他可能的字段名
                                    for key in ['photo', 'images', 'pictures', 'photos_url']:
                                        if key in poi_data:
                                            self.stdout.write(f'  找到字段 {key}: {poi_data[key]}')
                            else:
                                # 如果没有pois字段，尝试直接使用返回的数据
                                self.stdout.write(f'  无pois字段，使用根数据')
                                poi_data = poi_detail
                        else:
                            error_info = poi_detail.get('info', '未知错误') if poi_detail else '无响应'
                            self.stdout.write(
                                self.style.WARNING(f'  获取POI详情失败: {error_info}')
                            )
                    except Exception as e:
                        import traceback
                        self.stdout.write(
                            self.style.WARNING(f'  获取POI详情异常: {str(e)}')
                        )
                        self.stdout.write(f'  错误详情: {traceback.format_exc()}')

                    # 解析营业时间
                    open_time = None
                    close_time = None
                    if poi_data:
                        opentime = poi_data.get('opentime', '')
                        if opentime and ';' in opentime:
                            # 格式：09:00-17:00;09:00-17:00
                            time_ranges = opentime.split(';')
                            if time_ranges:
                                first_range = time_ranges[0]
                                if '-' in first_range:
                                    times = first_range.split('-')
                                    if len(times) == 2:
                                        try:
                                            from datetime import datetime
                                            open_time = datetime.strptime(times[0].strip(), '%H:%M').time()
                                            close_time = datetime.strptime(times[1].strip(), '%H:%M').time()
                                        except:
                                            pass
                    
                    # 解析评分和热度
                    rating = 4.0
                    popularity = 50
                    if poi_data:
                        # 高德地图评分通常是字符串，如"4.5"
                        rating_str = poi_data.get('rating', '')
                        if rating_str:
                            try:
                                rating = float(rating_str)
                            except:
                                pass
                        # 根据评分计算热度（评分越高，热度越高）
                        popularity = int(rating * 20)  # 5分制转100分制
                    
                    # 获取更详细的描述
                    description = poi.get('intro', '') or ''
                    if poi_data:
                        # 优先使用详情中的描述
                        detail_intro = poi_data.get('intro', '') or poi_data.get('content', '')
                        if detail_intro:
                            description = detail_intro
                    
                    # 解析门票价格（如果有的话）
                    ticket_price = Decimal('0.00')
                    if poi_data:
                        # 尝试从详情中获取价格信息
                        cost = poi_data.get('cost', '')
                        if cost:
                            # 可能包含"免费"、"¥50"等格式
                            import re
                            price_match = re.search(r'(\d+\.?\d*)', cost)
                            if price_match:
                                try:
                                    ticket_price = Decimal(price_match.group(1))
                                except:
                                    pass

                    # 提取POI ID（优先使用搜索结果的ID，如果没有则使用详情中的ID）
                    poi_id = poi_id_from_search or (poi_data.get('id', '') if poi_data else '')
                    
                    # 调试输出
                    if not poi_id:
                        self.stdout.write(f'  警告: POI ID为空，景点名称: {poi_name}')
                    
                    # 提取图片URL列表（不下载，只保存URL）
                    image_urls = []
                    if poi_data:
                        photos = poi_data.get('photos', [])
                        if not photos:
                            photos = poi_data.get('photo', [])
                        if isinstance(photos, str):
                            import json
                            try:
                                photos = json.loads(photos)
                            except:
                                photos = []
                        if isinstance(photos, list):
                            for photo in photos[:5]:  # 最多保存5张图片URL
                                if isinstance(photo, dict) and photo.get('url'):
                                    image_urls.append(photo['url'])
                                elif isinstance(photo, str):
                                    image_urls.append(photo)
                    
                    # 调试输出
                    self.stdout.write(f'  POI ID: {poi_id}')
                    self.stdout.write(f'  图片URL数量: {len(image_urls)}')
                    if image_urls:
                        self.stdout.write(f'  第一张图片URL: {image_urls[0][:60]}...')
                    
                    # 创建或更新景点
                    attraction, created = Attraction.objects.get_or_create(
                        name=poi_name,
                        defaults={
                            'latitude': latitude,
                            'longitude': longitude,
                            'address': address,
                            'description': description,
                            'ticket_price': ticket_price,
                            'open_time': open_time,
                            'close_time': close_time,
                            'popularity': popularity,
                            'rating': rating,
                            'amap_poi_id': poi_id,
                            'amap_image_urls': image_urls,
                        }
                    )

                    if created:
                        created_count += 1
                        self.stdout.write(
                            self.style.SUCCESS(f'[{idx}/{len(all_pois)}] ✓ 创建景点: {poi_name}')
                        )
                    elif update_existing:
                        # 更新已存在的景点
                        attraction.latitude = latitude
                        attraction.longitude = longitude
                        if address:
                            attraction.address = address
                        if description:
                            attraction.description = description
                        if open_time:
                            attraction.open_time = open_time
                        if close_time:
                            attraction.close_time = close_time
                        if rating:
                            attraction.rating = rating
                        if popularity:
                            attraction.popularity = popularity
                        if ticket_price:
                            attraction.ticket_price = ticket_price
                        # 更新POI ID和图片URL
                        if poi_id:
                            attraction.amap_poi_id = poi_id
                            self.stdout.write(f'  更新POI ID: {poi_id}')
                        if image_urls:
                            attraction.amap_image_urls = image_urls
                            self.stdout.write(f'  更新图片URL: {len(image_urls)}张')
                        attraction.save()
                        updated_count += 1
                        self.stdout.write(
                            self.style.SUCCESS(f'[{idx}/{len(all_pois)}] ↻ 更新景点: {poi_name}')
                        )
                    else:
                        self.stdout.write(
                            self.style.WARNING(f'[{idx}/{len(all_pois)}] - 跳过已存在: {poi_name}')
                        )
                        continue

                    # 不再下载图片，只保存URL（已在上面的代码中处理）
                    # 保留此代码块用于兼容性，但实际不执行下载操作
                    if False and not skip_images and poi_detail and poi_data:
                        try:
                            # 高德地图API返回的图片数据可能在photos字段中
                            photos = poi_data.get('photos', [])
                            
                            # 如果没有photos字段，尝试其他可能的字段名
                            if not photos:
                                # 有些API返回格式可能是photo或其他字段名
                                photos = poi_data.get('photo', [])
                            
                            # 如果photos是字符串，尝试解析
                            if isinstance(photos, str):
                                import json
                                try:
                                    photos = json.loads(photos)
                                except:
                                    photos = []
                            
                            # 确保photos是列表
                            if not isinstance(photos, list):
                                photos = []
                            
                            # 调试：打印图片数据
                            self.stdout.write(f'  图片数据: {len(photos)} 张')
                            if photos:
                                self.stdout.write(f'  第一张图片: {photos[0] if isinstance(photos[0], dict) else "非字典格式"}')
                            
                            if photos:
                                # 检查是否已有图片
                                existing_images = AttractionImage.objects.filter(attraction=attraction)
                                if existing_images.exists() and not update_existing:
                                    self.stdout.write(f'  跳过图片下载（已存在）')
                                else:
                                    # 如果更新已存在，先删除旧图片
                                    if update_existing and existing_images.exists():
                                        existing_images.delete()
                                        self.stdout.write(f'  删除旧图片')
                                    
                                    # 下载图片（最多下载前5张）
                                    for photo_idx, photo in enumerate(photos[:5]):
                                        try:
                                            # 高德地图API返回的图片数据结构可能是：
                                            # 1. {'url': '...', 'title': '...'}
                                            # 2. 字符串URL
                                            # 3. 其他格式
                                            
                                            photo_url = None
                                            
                                            if isinstance(photo, dict):
                                                # 尝试多个可能的字段名
                                                photo_url = (
                                                    photo.get('url') or 
                                                    photo.get('title') or 
                                                    photo.get('image') or
                                                    photo.get('photo_url') or
                                                    photo.get('pic_url')
                                                )
                                            elif isinstance(photo, str):
                                                photo_url = photo
                                            else:
                                                self.stdout.write(f'  图片 {photo_idx + 1} 数据格式不支持: {type(photo)}')
                                                continue
                                            
                                            if not photo_url:
                                                self.stdout.write(f'  图片 {photo_idx + 1} URL为空，跳过')
                                                self.stdout.write(f'  图片数据: {photo}')
                                                continue
                                            
                                            # 确保URL是完整的HTTP/HTTPS URL
                                            if not photo_url.startswith('http://') and not photo_url.startswith('https://'):
                                                # 如果URL不完整，尝试构建完整URL
                                                if photo_url.startswith('/'):
                                                    photo_url = 'https://restapi.amap.com' + photo_url
                                                elif photo_url.startswith('//'):
                                                    photo_url = 'https:' + photo_url
                                                else:
                                                    # 尝试使用高德地图的图片服务URL
                                                    # 高德地图的图片URL格式通常是：https://restapi.amap.com/v3/staticmap?...
                                                    # 或者可能是相对路径，需要拼接
                                                    self.stdout.write(f'  图片 {photo_idx + 1} URL格式可能无效: {photo_url[:100]}')
                                                    # 不跳过，尝试直接下载看看
                                            
                                            self.stdout.write(f'  下载图片 {photo_idx + 1}: {photo_url[:80]}...')
                                            
                                            # 下载图片
                                            image_file = create_image_file_from_url(
                                                photo_url,
                                                file_name=f'{poi_name}_{photo_idx + 1}.jpg'
                                            )
                                            
                                            # 创建图片记录
                                            AttractionImage.objects.create(
                                                attraction=attraction,
                                                image=image_file,
                                                is_primary=(photo_idx == 0)  # 第一张设为主图
                                            )
                                            
                                            image_count += 1
                                            self.stdout.write(
                                                self.style.SUCCESS(f'  ✓ 下载图片 {photo_idx + 1}/{min(len(photos), 5)}')
                                            )
                                            
                                            time.sleep(0.3)  # 避免下载过快
                                        except Exception as e:
                                            import traceback
                                            self.stdout.write(
                                                self.style.WARNING(f'  图片 {photo_idx + 1} 下载失败: {str(e)}')
                                            )
                                            # 只在调试模式下打印详细错误
                                            if settings.DEBUG:
                                                self.stdout.write(f'  错误详情: {traceback.format_exc()}')
                            else:
                                self.stdout.write(
                                    self.style.WARNING(f'  未找到图片数据（photos字段为空）')
                                )
                                # 调试：打印poi_data的所有键，帮助排查
                                all_keys = list(poi_data.keys())
                                self.stdout.write(f'  POI数据所有字段: {all_keys}')
                                
                                # 尝试查找可能包含图片URL的其他字段
                                possible_image_fields = ['photo', 'image', 'pic', 'img', 'picture', 'photos_url', 'image_url']
                                for field in possible_image_fields:
                                    if field in poi_data:
                                        field_value = poi_data[field]
                                        self.stdout.write(f'  找到字段 {field}: {type(field_value)} = {str(field_value)[:100]}')
                                
                                # 打印完整的poi_data（仅前500字符）用于调试
                                if settings.DEBUG:
                                    import json
                                    try:
                                        poi_data_str = json.dumps(poi_data, ensure_ascii=False, indent=2)[:500]
                                        self.stdout.write(f'  POI数据预览: {poi_data_str}...')
                                    except:
                                        self.stdout.write(f'  POI数据无法序列化')
                        except Exception as e:
                            import traceback
                            self.stdout.write(
                                self.style.WARNING(f'  处理图片失败: {str(e)}')
                            )
                            self.stdout.write(f'  错误详情: {traceback.format_exc()}')

                except Exception as e:
                    error_count += 1
                    self.stdout.write(
                        self.style.ERROR(f'[{idx}/{len(all_pois)}] ✗ 处理失败: {poi.get("name", "未知")} - {str(e)}')
                    )

            # 输出统计信息
            self.stdout.write('')
            self.stdout.write(self.style.SUCCESS('=' * 60))
            self.stdout.write(self.style.SUCCESS('同步完成！'))
            self.stdout.write(self.style.SUCCESS('=' * 60))
            self.stdout.write(f'创建景点: {created_count}')
            self.stdout.write(f'更新景点: {updated_count}')
            self.stdout.write(f'下载图片: {image_count}')
            self.stdout.write(f'错误数量: {error_count}')

        except Exception as e:
            self.stdout.write(
                self.style.ERROR(f'同步失败: {str(e)}')
            )

